package com.zxb.base.autoform.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zxb.base.generator.service.DdlService;
import com.zxb.base.generator.vo.ColumnVo;
import com.zxb.core.common.A;
import com.zxb.core.common.C;
import com.zxb.core.common.R;
import com.zxb.core.dao.autoform.*;
import com.zxb.base.autoform.enm.ColumnFixedEnum;
import com.zxb.base.autoform.vo.LayoutUpdateVo;
import com.zxb.base.autoform.util.TableUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author Zxb
 */
@RestController
@RequiredArgsConstructor
public class ColumnController {
    private static final String SCHEMA = "base";
    private final DiyFormDao formDao;
    private final DiyColumnDao columnDao;
    private final DiyLayoutDao layoutDao;
    private final TableUtil tableUtil;
    private final DdlService ddlService;

    @PostMapping("/column/add")
    public R add(@RequestBody DiyColumn obj) {
        if (columnDao.exists(
                new QueryWrapper<DiyColumn>()
                        .lambda()
                        .eq(DiyColumn::getFormId, obj.getFormId())
                        .eq(DiyColumn::getName, obj.getName())
        )) {
            return R.error("字段名称已经存在");
        }
        if (columnDao.exists(
                new QueryWrapper<DiyColumn>()
                        .lambda()
                        .eq(DiyColumn::getFormId, obj.getFormId())
                        .eq(DiyColumn::getCode, obj.getCode())
        )) {
            return R.error("字段编码已经存在");
        }
        obj.setSearchStr(obj.getName() + obj.getCode());
        columnDao.save(obj);
        //统计字段数量
        Long columnCount = columnDao.count(new LambdaQueryWrapper<DiyColumn>()
                .eq(DiyColumn::getFormId, obj.getFormId()));
        formDao.lambdaUpdate()
                .eq(DiyForm::getId, obj.getFormId())
                .set(DiyForm::getColumnCount, columnCount.intValue())
                .update();
        return R.success();
    }

    @PostMapping("/column/update")
    public R update(@RequestBody DiyColumn obj) {
        DiyColumn old = columnDao.getById(obj.getId());
        A.isInDatabase(old, "字段");
        //缓存旧的编码和类型
        String oldCode = old.getCode();
        String oldCompType = old.getCompType();
        String oldDataType = old.getDataType();
        if (columnDao.exists(
                new QueryWrapper<DiyColumn>()
                        .lambda()
                        .eq(DiyColumn::getFormId, old.getFormId())
                        .eq(DiyColumn::getName, obj.getName())
                        .ne(DiyColumn::getId, old.getId())
        )) {
            return R.error("字段名称已经存在");
        }
        BeanUtil.copyProperties(obj, old, C.IGNORED_PROPERTIES);
        old.setSearchStr(obj.getName() + obj.getCode());
        //重置旧的类型和编码
        old.setCode(oldCode);
        old.setCompType(oldCompType);
        old.setDataType(oldDataType);
        columnDao.updateById(old);
        return R.success();
    }

    @PostMapping("/column/del")
    @Transactional(rollbackFor = Exception.class)
    public R del(@RequestBody List<Long> ids) {
        if (CollUtil.isNotEmpty(ids)) {
            DiyColumn column = columnDao.getById(ids.get(0));
            Long formId = column.getFormId();
            //删除字段相关布局设置
            layoutDao.remove(new QueryWrapper<DiyLayout>()
                    .lambda()
                    .in(DiyLayout::getColumnId, ids));
            //删除字段
            columnDao.removeBatchByIds(ids);
            //统计表单字段数量
            Long columnCount = columnDao.count(new QueryWrapper<DiyColumn>()
                    .lambda().eq(DiyColumn::getFormId, formId));
            formDao.lambdaUpdate()
                    .eq(DiyForm::getId, formId)
                    .set(DiyForm::getColumnCount, columnCount.intValue())
                    .update();
        }
        return R.success();
    }

    @GetMapping("/column/page")
    public R page(String searchStr, String formId, Integer page, Integer pageSize) {
        IPage<DiyColumn> pageParam = new Page<>(page, pageSize);
        QueryWrapper<DiyColumn> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<DiyColumn> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(DiyColumn::getFormId, Long.valueOf(formId));
        if (StrUtil.isNotBlank(searchStr)) {
            lambdaQueryWrapper.like(DiyColumn::getSearchStr, "%" + searchStr + "%");
        }
        lambdaQueryWrapper.orderByAsc(DiyColumn::getId);
        IPage<DiyColumn> result = columnDao.page(pageParam, queryWrapper);
        return R.success(result);
    }

    @GetMapping("/column/list")
    public R list(Long formId) {
        List<DiyColumn> columnList = columnDao.list(
                new QueryWrapper<DiyColumn>()
                        .lambda()
                        .eq(DiyColumn::getFormId, formId));
        return R.success(columnList);
    }

    @GetMapping("/column/count")
    public R countColumn(String formId) {
        long count = columnDao.count(new QueryWrapper<DiyColumn>()
                .lambda().eq(DiyColumn::getFormId, Long.valueOf(formId)));
        return R.success(count);
    }

    @PostMapping("/column/layout/update")
    public R updateColumnLayout(@RequestBody LayoutUpdateVo layoutUpdateVo) {
        Long formId = layoutUpdateVo.getFormId();
        String layoutType = layoutUpdateVo.getLayoutType();
        //删除原来字段布局
        layoutDao.remove(new QueryWrapper<DiyLayout>()
                .lambda()
                .eq(DiyLayout::getFormId, formId)
                .eq(DiyLayout::getType, layoutType));
        List<DiyLayout> layoutList = layoutUpdateVo.getLayoutList();
        layoutDao.saveBatch(layoutList);
        return R.success(layoutList.size());
    }

    @PostMapping("/column/sort")
    public R sortColumn(@RequestBody List<String> list) {
        AtomicInteger count = new AtomicInteger();
        list.stream().forEach(t -> {
            String[] arr = t.split(":");
            Long columnId = Long.valueOf(arr[0]);
            DiyColumn column = columnDao.getById(columnId);
            Integer sort = Integer.valueOf(arr[1]);
            String type = arr[2];
            DiyLayout layout = layoutDao.getOne(new QueryWrapper<DiyLayout>()
                    .lambda()
                    .eq(DiyLayout::getColumnId, columnId)
                    .eq(DiyLayout::getType, type));
            if (layout == null) {
                layout = new DiyLayout();
                layout.setFormId(column.getFormId());
                layout.setColumnId(columnId);
                layout.setColumnCode(column.getCode());
                layout.setColumnType(column.getCompType());
                layout.setSort(sort);
                layout.setOffset(0);
                layout.setSpan(12);
                layout.setType(type);
                layoutDao.save(layout);
            } else {
                layout.setSort(sort);
                layoutDao.updateById(layout);
            }
            count.getAndIncrement();
        });
        return R.success(count.get());
    }

    @GetMapping("/column/layout")
    public R findColumnLayout(Long formId, String layoutType) {
        List<DiyLayout> layoutList = layoutDao.list(new QueryWrapper<DiyLayout>()
                .lambda()
                .eq(DiyLayout::getFormId, formId)
                .eq(DiyLayout::getType, layoutType));
        return R.success(layoutList);
    }

    @PostMapping("/column/sync")
    public R syncDatabaseColumn(@RequestBody Long formId) {
        DiyForm form = formDao.getById(Long.valueOf(formId));
        List<DiyColumn> columns = columnDao.list(
                new LambdaQueryWrapper<DiyColumn>()
                        .eq(DiyColumn::getFormId, formId)
        );
        List<ColumnVo> columnVoList = columns.stream().map(t -> {
            ColumnVo columnVo = new ColumnVo();
            columnVo.setName(t.getCode());
            columnVo.setType(t.getDataType());
            columnVo.setComment(t.getName());
            return columnVo;
        }).collect(Collectors.toList());
        if (ddlService.isTableExist(SCHEMA, form.getCode())) {
            ddlService.mergeColumnsForTable(SCHEMA, form.getCode(), columnVoList);
        } else {
            ddlService.addTable(SCHEMA, form.getCode(), columnVoList);
        }
        return R.success();
    }
}
